package cz.zcu.fav.rat.dataaccess.service;

import java.io.Serializable;
import java.util.Properties;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class SettingsFactory implements Serializable
{
	private transient Logger logger;

	private static final long serialVersionUID = -4417169403701672630L;

	private static String MINIMUM_RESERVATION_DURATION_KEY = "reservation.duration.minimum";
	private static String RESERVATION_EXPIRATION_LIMIT_KEY = "reservation.expiration.limit";
	private static String MAXIMUM_RESERVATION_DURATION_KEY = "reservation.duration.maximum";

	private static String MAXIMUM_PERIODICAL_COUNT_KEY = "reservation.periodical.maximum";

	// cca year
	private static int MAXIMUM_PERIODICAL_COUNT_DEFAULT = 52;

	// 1 hour
	private static Duration MINIMUM_RESERVATION_LENGTH_DEFAULT = Duration
			.standardHours(1);
	// week
	private static Duration MAXIMUM_RESERVATION_LENGTH_WEEK = Duration
			.standardDays(7);

	private static Duration MAXIMUM_RESERVATION_LENGTH_DEFAULT = MAXIMUM_RESERVATION_LENGTH_WEEK;

	// 10 minutes
	private static Duration RESERVATION_EXPIRATION_LIMIT_DEFAULT = Duration
			.standardMinutes(10);

	@Autowired
	@Qualifier(value = "ratProperties")
	private Properties serverProperties;
	private Duration minimumReservationDuration;
	private Duration maximumReservationDuration;
	private int maximumPeriodicalCount;
	private Duration reservationExpirationLimit;

	private Logger getLogger()
	{
		if (logger == null)
		{
			logger = Logger.getLogger(SettingsFactory.class);
		}
		return logger;
	}

	@PostConstruct
	public void init()
	{
		try
		{
			reservationExpirationLimit = Duration.standardMinutes(Long
					.parseLong((String) serverProperties
							.get(RESERVATION_EXPIRATION_LIMIT_KEY)));
		} catch (NumberFormatException ex)
		{
			getLogger()
					.warn("Property name " + reservationExpirationLimit
							+ " cannot be parsed. Using default value instead.",
							ex);
			reservationExpirationLimit = RESERVATION_EXPIRATION_LIMIT_DEFAULT;
		}

		try
		{
			maximumPeriodicalCount = Integer.parseInt((String) serverProperties
					.get(MAXIMUM_PERIODICAL_COUNT_KEY));
		} catch (NumberFormatException ex)
		{
			getLogger()
					.warn("Property name " + MAXIMUM_PERIODICAL_COUNT_KEY
							+ " cannot be parsed. Using default value instead.",
							ex);
			maximumPeriodicalCount = MAXIMUM_PERIODICAL_COUNT_DEFAULT;
		}

		try
		{
			minimumReservationDuration = Duration.standardMinutes(Long
					.parseLong((String) serverProperties
							.get(MINIMUM_RESERVATION_DURATION_KEY)));
		} catch (NumberFormatException ex)
		{
			getLogger()
					.warn("Property name " + MINIMUM_RESERVATION_DURATION_KEY
							+ " cannot be parsed. Using default value instead.",
							ex);
			minimumReservationDuration = MINIMUM_RESERVATION_LENGTH_DEFAULT;
		}

		try
		{
			maximumReservationDuration = Duration.standardMinutes(Long
					.parseLong((String) serverProperties
							.get(MAXIMUM_RESERVATION_DURATION_KEY)));
			if (maximumReservationDuration
					.isLongerThan(MAXIMUM_RESERVATION_LENGTH_DEFAULT))
			{
				maximumReservationDuration = MAXIMUM_RESERVATION_LENGTH_WEEK;
				getLogger()
						.warn("Property name "
								+ MAXIMUM_RESERVATION_DURATION_KEY
								+ " cannot be longer than one week. Using default value instead.");
			}
		} catch (NumberFormatException ex)
		{
			getLogger()
					.warn("Property name " + MAXIMUM_RESERVATION_DURATION_KEY
							+ " cannot be parsed. Using default value instead.",
							ex);
			minimumReservationDuration = MAXIMUM_RESERVATION_LENGTH_DEFAULT;
		}

	}

	
	
	public Duration getReservationExpirationLimit()
	{
		return reservationExpirationLimit;
	}

	public void setReservationExpirationLimit(Duration reservationExpirationLimit)
	{
		this.reservationExpirationLimit = reservationExpirationLimit;
	}

	public Duration getMinimumReservationDuration()
	{
		return minimumReservationDuration;
	}

	public Duration getMaximumReservationDuration()
	{
		return maximumReservationDuration;
	}

	public int getMaximumPeriodicalCount()
	{
		return maximumPeriodicalCount;
	}

}
